/**
 * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved.
 * 
 * @file    gh3x2x_demo_user.c
 * 
 * @brief   gh3x2x driver lib demo code that user defined
 * 
 * @author  
 * 
 */

/* includes */
#include "stdint.h"
#include "string.h"
#include "gh3x2x_drv.h"
#include "gh3x2x_demo_config.h"
#include "gh3x2x_demo_inner.h"
#include "gh3x2x_demo.h"

#if (__DRIVER_LIB_MODE__ == __DRV_LIB_WITH_ALGO__)
#include "gh3x2x_demo_algo_call.h"
#endif

#if (__GH3X2X_MP_MODE__)
#include "gh3x2x_mp_common.h"
#endif

#include "nrf_drv_spi.h"
#include "nrf_drv_gpiote.h"
#include "nrf_delay.h"
#include "hr_task.h"

#include "board_cfg.h"

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"



//SPI驱动程序实例ID,ID和外设编号对应，0:SPI0  1:SPI1 2:SPI2
//定义名称为spi的SPI驱动程序实例
static const nrf_drv_spi_t gh3026_spi = NRF_DRV_SPI_INSTANCE(1); 


#define    GH3026_SPI_CS_LOW        nrf_gpio_pin_clear(SPI_GH3026_SS_PIN)   //片选输出低电平：使能芯片
#define    GH3026_SPI_CS_HIGH       nrf_gpio_pin_set(SPI_GH3026_SS_PIN)     //片选输出高电平：取消片选


#define GSENSOR_FIFO_CNT_PER_SECONDS		(__GSENSOR_DATA_BUFFER_SIZE__)
#define GSENSOR_SOFT_FIFO_BUFFER_MAX_LEN	GSENSOR_FIFO_CNT_PER_SECONDS	//(256)
#define TEMP_SOFT_FIFO_BUFFER_MAX_LEN		(26)	//(256)

#define GSENSOR_FORMAT_CONVERT(x)			(x/16)	// x/( (1000/512) * ((2^(15))/4000) )

static uint16_t record_idx = 0;
static uint16_t temp_fifo_buf_idx = 0;
static STGsensorRawdata temp_fifo_buf[TEMP_SOFT_FIFO_BUFFER_MAX_LEN];
static bool fifo_put_valid = false;

extern GU16 gsensor_soft_fifo_buffer_index;

extern uint8_t g_heart_value;        //记录心率值


#if ( __GH3X2X_INTERFACE__ == __GH3X2X_INTERFACE_I2C__ )

/* i2c interface */
/**
 * @fn     void hal_gh3x2x_i2c_init(void)
 * 
 * @brief  hal i2c init for gh3x2x
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void hal_gh3x2x_i2c_init(void)
{

    /* code implement by user */
    GOODIX_PLANFROM_I2C_INIT_ENTITY();

}

/**
 * @fn     uint8_t hal_gh3x2x_i2c_write(uint8_t device_id, const uint8_t write_buffer[], uint16_t length)
 * 
 * @brief  hal i2c write for gh3x2x
 *
 * @attention   device_id is 8bits, if platform i2c use 7bits addr, should use (device_id >> 1)
 *
 * @param[in]   device_id       device addr
 * @param[in]   write_buffer    write data buffer
 * @param[in]   length          write data len
 * @param[out]  None
 *
 * @return  status
 * @retval  #1      return successfully
 * @retval  #0      return error
 */
GU8 hal_gh3x2x_i2c_write(GU8 device_id, const GU8 write_buffer[], GU16 length)
{
    uint8_t ret = 1;

    /* code implement by user */

    GOODIX_PLANFROM_I2C_WRITE_ENTITY(device_id, write_buffer,length);
    return ret;
}

/**
 * @fn     uint8_t hal_gh3x2x_i2c_read(uint8_t device_id, const uint8_t write_buffer[], uint16_t write_length,
 *                            uint8_t read_buffer[], uint16_t read_length)
 * 
 * @brief  hal i2c read for gh3x2x
 *
 * @attention   device_id is 8bits, if platform i2c use 7bits addr, should use (device_id >> 1)
 *
 * @param[in]   device_id       device addr
 * @param[in]   write_buffer    write data buffer
 * @param[in]   write_length    write data len
 * @param[in]   read_length     read data len
 * @param[out]  read_buffer     pointer to read buffer
 *
 * @return  status
 * @retval  #1      return successfully
 * @retval  #0      return error
 */
GU8 hal_gh3x2x_i2c_read(GU8 device_id, const GU8 write_buffer[], GU16 write_length, GU8 read_buffer[], GU16 read_length)
{
    uint8_t ret = 1;

    /* code implement by user */

    GOODIX_PLANFROM_I2C_READ_ENTITY(device_id, write_buffer, write_length, read_buffer, read_length);
    return ret;
}

#else // __GH3X2X_INTERFACE__ == __GH3X2X_INTERFACE_SPI__


/* spi interface */
/**
 * @fn     void hal_gh3x2x_spi_init(void)
 * 
 * @brief  hal spi init for gh3x2x
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */


void hal_gh3x2x_spi_init(void)
{
    /* init spi and cs pin */
    GOODIX_PLANFROM_SPI_INIT_ENTITY();

    //此处先设置清除hr复位引脚，避免导致下一行代码异常无法启动；具体异常原因不知道，就是下一行代码挂掉了
    
    nrf_gpio_pin_set(GH3026_RST_PIN);
    nrf_delay_ms(100);
    nrf_gpio_pin_clear(GH3026_RST_PIN);
    nrf_delay_ms(100);
    nrf_gpio_pin_set(GH3026_RST_PIN);
    nrf_delay_ms(20);

    //配置用于SPI片选的引脚为输出
    nrf_gpio_cfg_output(SPI_GH3026_SS_PIN);

    //使用默认配置参数初始化SPI配置结构体
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    
    //SPI信号连接的引脚配置
    spi_config.ss_pin       = NRF_DRV_SPI_PIN_NOT_USED;
    spi_config.miso_pin     = SPI_GH3026_MISO_PIN;
    spi_config.mosi_pin     = SPI_GH3026_MOSI_PIN;
    spi_config.sck_pin      = SPI_GH3026_SCK_PIN;
    spi_config.frequency    = NRF_DRV_SPI_FREQ_8M;
    
    //初始化SPI
    APP_ERROR_CHECK(nrf_drv_spi_init(&gh3026_spi, &spi_config, NULL, NULL));

    
    g_heart_value = 0;
    fifo_put_valid = true;
}

void hal_gh3x2x_deinit(void)
{
    //关中断
    nrf_drv_gpiote_in_event_enable(GH3026_INT_PIN, true);
    nrfx_gpiote_in_uninit(GH3026_INT_PIN);
   
    nrf_drv_spi_uninit(&gh3026_spi);
    
    fifo_put_valid = false;
}


/**
 * @fn     GU8 hal_gh3x2x_spi_write(GU8 write_buffer[], GU16 length)
 * 
 * @brief  hal spi write for gh3x2x
 *
 * @attention   if __GH3X2X_SPI_TYPE__ == __GH3X2X_SPI_TYPE_SOFTWARE_CS__  , user need generate timming: write_buf[0](W) + write_buf[1](W) + ...
 * @attention   if __GH3X2X_SPI_TYPE__ == __GH3X2X_SPI_TYPE_HARDWARE_CS__  , user need generate timming: CS LOW  + write_buf[0](W) + write_buf[1](W) + ... + CS HIGH
 *
 * @param[in]   write_buffer    write data buffer
 * @param[in]   length          write data len
 * @param[out]  None
 *
 * @return  status
 * @retval  #1      return successfully
 * @retval  #0      return error
 */
GU8 hal_gh3x2x_spi_write(GU8 write_buffer[], GU16 length)
{
    GU8 ret = 1;

    
//    GOODIX_PLANFROM_SPI_WRITE_ENTITY(write_buffer, length);


    //启动数据传输
    ret = nrf_drv_spi_transfer(&gh3026_spi, write_buffer, length, NULL, 0);
    
    return ret;
}


#if (__GH3X2X_SPI_TYPE__ == __GH3X2X_SPI_TYPE_SOFTWARE_CS__) 
/**
 * @fn     GU8 hal_gh3x2x_spi_read(GU8 read_buffer[], GU16 length)
 * 
 * @brief  hal spi read for gh3x2x
 *
 * @attention   user need generate timming: read_buf[0](R) + write_buf[1](R) + ... 
 *
 * @param[in]   read_length     read data len
 * @param[out]  read_buffer     pointer to read buffer
 *
 * @return  status
 * @retval  #1      return successfully
 * @retval  #0      return error
 */
GU8 hal_gh3x2x_spi_read(GU8 read_buffer[], GU16 length)
{
    GU8 ret = 1;

//    GOODIX_PLANFROM_SPI_READ_ENTITY();

    ret = nrf_drv_spi_transfer(&gh3026_spi, NULL, 0, read_buffer, length);

    return ret;
}
#elif (__GH3X2X_SPI_TYPE__ == __GH3X2X_SPI_TYPE_HARDWARE_CS__)
/**
 * @fn     GU8 hal_gh3x2x_spi_write_F1_and_read(GU8 read_buffer[], GU16 length)
 * 
 * @brief  hal spi write F1 and read for gh3x2x
 *
 * @attention    user need generate timming: CS LOW + F1(W) + read_buf[0](R) + read_buf[1](R) + ... + CS HIGH
 *
 * @param[in]   write_buf     write data
 * @param[in]   length     write data len
 *
 * @return  status
 * @retval  #1      return successfully
 * @retval  #0      return error
 */
GU8 hal_gh3x2x_spi_write_F1_and_read(GU8 read_buffer[], GU16 length)
{
    GU8 ret = 1;
    
     GOODIX_PLANFROM_SPI_READ_ENTITY();
    
    return ret;
}
#endif

/**
 * @fn     void hal_gh3x2x_spi_cs_ctrl(GU8 cs_pin_level)
 * 
 * @brief  hal spi cs pin ctrl for gh3x2x
 *
 * @attention   pin level set 1 [high level] or 0 [low level]
 *
 * @param[in]   cs_pin_level     spi cs pin level
 * @param[out]  None
 *
 * @return  None
 */
#if (__GH3X2X_SPI_TYPE__ == __GH3X2X_SPI_TYPE_SOFTWARE_CS__) 
void hal_gh3x2x_spi_cs_ctrl(GU8 cs_pin_level)
{

    GOODIX_PLANFROM_SPI_CS_CTRL_ENTITY();

    if (cs_pin_level)
    {
        GH3026_SPI_CS_HIGH;
    }
    else
    {
        GH3026_SPI_CS_LOW;
    }

}
#endif

#endif

#if __SUPPORT_HARD_RESET_CONFIG__

/**
 * @fn     void hal_gh3x2x_int_init(void)
 * 
 * @brief  gh3x2x int init
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */



void hal_gh3x2x_reset_pin_init(void)
{
    GOODIX_PLANFROM_RESET_PIN_INIT_ENTITY();

    nrf_gpio_cfg_output(GH3026_RST_PIN);

    nrf_gpio_pin_clear(GH3026_RST_PIN);
    nrf_delay_ms(5);
    nrf_gpio_pin_set(GH3026_RST_PIN);
}

/**
 * @fn     void hal_gh3x2x_reset_pin_ctrl(GU8 pin_level)
 * 
 * @brief  hal reset pin ctrl for gh3x2x
 *
 * @attention   pin level set 1 [high level] or 0 [low level]
 *
 * @param[in]   pin_level     reset pin level
 * @param[out]  None
 *
 * @return  None
 */

void hal_gh3x2x_reset_pin_ctrl(GU8 pin_level)
{

   GOODIX_PLANFROM_SPI_RESET_PIN_ENTITY();

   if (pin_level)
   {
       nrf_gpio_pin_set(GH3026_RST_PIN);
   }
   else
   {
       nrf_gpio_pin_clear(GH3026_RST_PIN);
   }
}

#endif

/**
 * @fn     void hal_gh3x2x_int_init(void)
 * 
 * @brief  gh3x2x int init
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void hal_gh3x2x_int_init(void)
{
    GOODIX_PLANFROM_INT_INIT_ENTITY();

    //定义GPIOTE配置结构体，配置为下降沿触发（按键是低电平有效），低精度  
    //gpio port 唤醒
    nrf_drv_gpiote_in_config_t int_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);	

    //开启引脚的上拉电阻
    int_config.pull = NRF_GPIO_PIN_PULLUP;
    nrf_drv_gpiote_in_init(GH3026_INT_PIN, &int_config, hal_gh3x2x_int_handler_call_back);
    nrf_drv_gpiote_in_event_enable(GH3026_INT_PIN, true);
}

#if (__NORMAL_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__ || __MIX_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__)
/**
 * @fn     void hal_gh3x2x_int_handler_call_back(void)
 * 
 * @brief  call back of gh3x2x int handler
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void hal_gh3x2x_int_handler_call_back(void)
{
    if (Gh3x2xGetInterruptMode() == __NORMAL_INT_PROCESS_MODE__)
    {
        GH3x2x_SetNeedWakeUpGh3x2xFlag(GH3x2x_GetNeedWakeUpGh3x2xFlagBeforeInt());  //not need wake up gh3x2x when process int event
        g_uchGh3x2xIntCallBackIsCalled = 1;
#if (__GH3X2X_MP_MODE__)
        GH3X2X_MP_SET_INT_FLAG();  //gh3x2x mp test must call it
#endif
        GOODIX_PLANFROM_INT_HANDLER_CALL_BACK_ENTITY();

//        NRF_LOG_INFO("hal_gh3x2x_int_handler_call_back");
        //中断处理
        hr_task_msg_send(HR_EVT_INT);
    }
}
#endif

void app_hr_gsensor_data_queue_put(uint16_t *pu16AccData)
{
	if(false == fifo_put_valid)
	{
		return;
	}
	
	if ((pu16AccData[0] <= 0) && (pu16AccData[1] <= 0) && (pu16AccData[2] <= 0))
	{
		return;
	}

	if (temp_fifo_buf_idx < TEMP_SOFT_FIFO_BUFFER_MAX_LEN)
	{
		temp_fifo_buf[temp_fifo_buf_idx].sXAxisVal = GSENSOR_FORMAT_CONVERT((int16_t)pu16AccData[0]);
		temp_fifo_buf[temp_fifo_buf_idx].sYAxisVal = GSENSOR_FORMAT_CONVERT((int16_t)pu16AccData[1]);
		temp_fifo_buf[temp_fifo_buf_idx].sZAxisVal = GSENSOR_FORMAT_CONVERT((int16_t)pu16AccData[2]);
		temp_fifo_buf_idx++;
	}
	else
	{
		for (uint16_t i = 0; i < (TEMP_SOFT_FIFO_BUFFER_MAX_LEN-1); i++)
		{
			temp_fifo_buf[i].sXAxisVal = temp_fifo_buf[i+1].sXAxisVal;
			temp_fifo_buf[i].sYAxisVal = temp_fifo_buf[i+1].sYAxisVal;
			temp_fifo_buf[i].sZAxisVal = temp_fifo_buf[i+1].sZAxisVal;
		}
		temp_fifo_buf[TEMP_SOFT_FIFO_BUFFER_MAX_LEN-1].sXAxisVal = GSENSOR_FORMAT_CONVERT((int16_t)pu16AccData[0]);
		temp_fifo_buf[TEMP_SOFT_FIFO_BUFFER_MAX_LEN-1].sYAxisVal = GSENSOR_FORMAT_CONVERT((int16_t)pu16AccData[1]);
		temp_fifo_buf[TEMP_SOFT_FIFO_BUFFER_MAX_LEN-1].sZAxisVal = GSENSOR_FORMAT_CONVERT((int16_t)pu16AccData[2]);
	}

	if (record_idx < TEMP_SOFT_FIFO_BUFFER_MAX_LEN)
	{
		record_idx++;
	}
}

/**
 * @fn     void hal_gsensor_start_cache_data(void)
 * 
 * @brief  Start cache gsensor data for gh3x2x
 *
 * @attention   This function will be called when start gh3x2x sampling.
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void hal_gsensor_start_cache_data(void)
{
    GOODIX_PLANFROM_INT_GS_START_CACHE_ENTITY();
    
    EXAMPLE_LOG("hal_gsensor_start_cache_data");
//    Gh3x2xDemoFunctionSampleRateSet(GH3X2X_FUNCTION_HR | GH3X2X_FUNCTION_ADT, 25);
}

/**
 * @fn     void hal_gsensor_stop_cache_data(void)
 * 
 * @brief  Stop cache gsensor data for gh3x2x
 *
 * @attention   This function will be called when stop gh3x2x sampling.
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void hal_gsensor_stop_cache_data(void)
{
        
    GOODIX_PLANFROM_INT_GS_STOP_CACHE_ENTITY();
}

void hal_cap_start_cache_data(void)
{
    GOODIX_PLANFROM_INT_CAP_START_CACHE_ENTITY();
}

void hal_cap_stop_cache_data(void)
{
    GOODIX_PLANFROM_INT_CAP_STOP_CACHE_ENTITY();
}

void hal_temp_start_cache_data(void)
{
    GOODIX_PLANFROM_INT_TEMP_START_CACHE_ENTITY();
}

void hal_temp_stop_cache_data(void)
{
    GOODIX_PLANFROM_INT_TEMP_STOP_CACHE_ENTITY();
}

void hal_gh3x2x_write_cap_to_flash(GS32 WearCap1,GS32 UnwearCap1,GS32 WearCap2,GS32 UnwearCap2)
{
    GOODIX_PLANFROM_WRITE_CAP_TO_FLASH_ENTITY();
}
void hal_gh3x2x_read_cap_from_flash(GS32* WearCap1,GS32* UnwearCap1,GS32* WearCap2,GS32* UnwearCap2)
{
    GOODIX_PLANFROM_READ_CAP_FROM_FLASH_ENTITY();
}

/**
 * @fn     void hal_gsensor_drv_get_fifo_data(STGsensorRawdata gsensor_buffer[], GU16 *gsensor_buffer_index)
 * 
 * @brief  get gsensor fifo data
 *
 * @attention   When read fifo data of GH3x2x, will call this function to get corresponding cached gsensor data.
 *
 * @param[in]   None
 * @param[out]  gsensor_buffer          pointer to gsensor data buffer
 * @param[out]  gsensor_buffer_index    pointer to number of gsensor data(every gsensor data include x,y,z axis data)
 *
 * @return  None
 */
void hal_gsensor_drv_get_fifo_data(STGsensorRawdata gsensor_buffer[], GU16 *gsensor_buffer_index)
{
/**************************** WARNNING  START***************************************************/
/*  (*gsensor_buffer_index) can not be allowed bigger than __GSENSOR_DATA_BUFFER_SIZE__  ****************/
/* Be care for copying data to gsensor_buffer, length of gsensor_buffer is __GSENSOR_DATA_BUFFER_SIZE__ *****/
/**************************** WARNNING END*****************************************************/

//    GOODIX_PLANFROM_INT_GET_GS_DATA_ENTITY();

 
    if (false == fifo_put_valid)
    {
        fifo_put_valid = true;
        return;
    }
    
    if (record_idx > GSENSOR_FIFO_CNT_PER_SECONDS)
    {
        gsensor_soft_fifo_buffer_index = GSENSOR_FIFO_CNT_PER_SECONDS;
    }
    else
    {
        gsensor_soft_fifo_buffer_index = record_idx;
    }
    
    //EXAMPLE_LOG("fifo(%d): %d, %d, %d", temp_fifo_buf_idx, temp_fifo_buf[0].sXAxisVal, temp_fifo_buf[0].sYAxisVal, temp_fifo_buf[0].sZAxisVal);
//    EXAMPLE_LOG("fifo idx: %d, %d", gsensor_soft_fifo_buffer_index, record_idx);
    record_idx -= gsensor_soft_fifo_buffer_index;
    for (uint16_t i = 0; i < gsensor_soft_fifo_buffer_index; i++)
    {
        gsensor_buffer[i].sXAxisVal = temp_fifo_buf[i].sXAxisVal;
        gsensor_buffer[i].sYAxisVal = temp_fifo_buf[i].sYAxisVal;
        gsensor_buffer[i].sZAxisVal = temp_fifo_buf[i].sZAxisVal;
    }
    //memcpy((uint8_t*)&gs_soft_fifo_buf, (uint8_t*)&temp_fifo_buf, (gs_soft_fifo_buf_idx*3*sizeof(GS16)));

    while (gsensor_soft_fifo_buffer_index < GSENSOR_FIFO_CNT_PER_SECONDS)
    {
        if (gsensor_soft_fifo_buffer_index < GSENSOR_SOFT_FIFO_BUFFER_MAX_LEN)
        {
            gsensor_buffer[gsensor_soft_fifo_buffer_index].sXAxisVal = gsensor_buffer[gsensor_soft_fifo_buffer_index-1].sXAxisVal;
            gsensor_buffer[gsensor_soft_fifo_buffer_index].sYAxisVal = gsensor_buffer[gsensor_soft_fifo_buffer_index-1].sYAxisVal;
            gsensor_buffer[gsensor_soft_fifo_buffer_index].sZAxisVal = gsensor_buffer[gsensor_soft_fifo_buffer_index-1].sZAxisVal;
            gsensor_soft_fifo_buffer_index++;
        }
    }


/**************************** WARNNING: DO NOT REMOVE OR MODIFY THIS CODE   ---START***************************************************/
    if((*gsensor_buffer_index) > (__GSENSOR_DATA_BUFFER_SIZE__))
    {
        while(1);   // Fatal error !!!
    }
/**************************** WARNNING: DO NOT REMOVE OR MODIFY THIS CODE   ---END***************************************************/
}

void hal_cap_drv_get_fifo_data(STCapRawdata cap_data_buffer[], GU16 *cap_buffer_index)
{
    GOODIX_PLANFROM_INT_GET_CAP_DATA_ENTITY()  ;
    if((*cap_buffer_index) > (__CAP_DATA_BUFFER_SIZE__))
    {
        while(1);   // Fatal error !!!
    }
}
void hal_temp_drv_get_fifo_data(STTempRawdata temp_data_buffer[], GU16 *temp_buffer_index)
{
    GOODIX_PLANFROM_INT_GET_TEMP_DATA_ENTITY();
    if((*temp_buffer_index) > (__TEMP_DATA_BUFFER_SIZE__))
    {
        while(1);   // Fatal error !!!
    }
}

#if (__EXAMPLE_LOG_TYPE__)
/**
 * @fn     void GH3X2X_Log(char *log_string)
 * 
 * @brief  for debug version, log
 *
 * @attention   this function must define that use debug version lib
 *
 * @param[in]   log_string      pointer to log string
 * @param[out]  None
 *
 * @return  None
 */

#if __EXAMPLE_LOG_TYPE__ == __EXAMPLE_LOG_METHOD_0__
void GH3X2X_Log(GCHAR *log_string)
{
    GOODIX_PLANFROM_LOG_ENTITY();
}
#endif

#if __EXAMPLE_LOG_TYPE__ == __EXAMPLE_LOG_METHOD_1__
void GH3X2X_RegisterPrintf(int (**pPrintfUser)(const char *format, ...))
{
    //(*pPrintfUser) = printf;   //use printf in <stdio.h>  or use equivalent function in your platform
    GOODIX_PLANFROM_PRINTF_ENTITY();
}
#endif




#endif

/**
 * @fn     void Gh3x2x_BspDelayUs(GU16 usUsec)
 * 
 * @brief  Delay in us,user should register this function into driver lib
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */

void Gh3x2x_BspDelayUs(GU16 usUsec)
{
    GOODIX_PLANFROM_DELAY_US_ENTITY();

    nrf_delay_us(usUsec);
}

void GH3X2X_AdtFuncStartWithGsDetectHook(void)
{
    GOODIX_PLANFROM_START_WITH_CONFIRM_HOOK_ENTITY();
}

/**
 * @fn     void Gh3x2x_BspDelayMs(GU16 usMsec)
 * 
 * @brief  Delay in ms
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void Gh3x2x_BspDelayMs(GU16 usMsec)
{
    GOODIX_PLANFROM_DELAY_MS_ENTITY();

    nrf_delay_ms(usMsec);
}

#if (__FUNC_TYPE_SOFT_ADT_ENABLE__)
/**
 * @fn     void Gh3x2x_CreateAdtConfirmTimer(void)
 * 
 * @brief  Create a timer for adt confirm which will read gsensor data periodically
 *
 * @attention   Period of timer can be set by 
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
#if (__USE_POLLING_TIMER_AS_ADT_TIMER__)&&\
    (__POLLING_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__ || __MIX_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__)
#else
void Gh3x2xCreateAdtConfirmTimer(void)
{
    GOODIX_PLANFROM_CREAT_ADT_CONFIRM_ENTITY();
}
#endif

/**
 * @fn     void Gh3x2x_StartAdtConfirmTimer(void)
 * 
 * @brief  Start time of adt confirm to get g sensor
 *
 * @attention   None        
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
#if __FUNC_TYPE_SOFT_ADT_ENABLE__
#if (__USE_POLLING_TIMER_AS_ADT_TIMER__)&&\
    (__POLLING_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__ || __MIX_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__)
#else
void Gh3x2x_StartAdtConfirmTimer(void)
{
    GOODIX_PLANFROM_START_TIMER_ENTITY();
}
#endif
#endif

/**
 * @fn     void Gh3x2x_StopAdtConfirmTimer(void)
 * 
 * @brief  Stop time of adt confirm
 *
 * @attention   None        
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
#if __FUNC_TYPE_SOFT_ADT_ENABLE__
#if (__USE_POLLING_TIMER_AS_ADT_TIMER__)&&\
    (__POLLING_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__ || __MIX_INT_PROCESS_MODE__ == __INTERRUPT_PROCESS_MODE__)
#else
void Gh3x2x_StopAdtConfirmTimer(void)
{
    GOODIX_PLANFROM_STOP_TIMER_ENTITY();
}
#endif
#endif
#endif




/**
 * @fn     void Gh3x2x_UserHandleCurrentInfo(void)
 * 
 * @brief  handle gh3x2x chip current information for user
 *
 * @attention   None        
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void Gh3x2x_UserHandleCurrentInfo(void)
{
    //read or write  slotx current

    //GH3X2X_GetSlotLedCurrent(0,0); //read slot 0  drv 0
    //GH3X2X_GetSlotLedCurrent(1,0); // read  slot 1  drv 0

    //GH3X2X_SlotLedCurrentConfig(0,0,50);  //set slot0 drv0 50 LSB
    //GH3X2X_SlotLedCurrentConfig(1,0,50);  //set slot1 drv0 50 LSB
}

#if (__SUPPORT_PROTOCOL_ANALYZE__)

void* gh3x2x_ble_send_timer = NULL;               //20hz timer

/**
 * @fn     void Gh3x2x_HalSerialSendData(GU8* uchTxDataBuf, GU16 usBufLen)
 *
 * @brief  Serial send data
 *
 * @attention   None
 *
 * @param[in]   uchTxDataBuf        pointer to data buffer to be transmitted
 * @param[in]   usBufLen            data buffer length
 * @param[out]  None
 *
 * @return  None
 */
void Gh3x2x_HalSerialSendData(GU8* uchTxDataBuf, GU16 usBufLen)
{
    GOODIX_PLANFROM_SERIAL_SEND_ENTITY();

    gh3x2x_ble_data_send(uchTxDataBuf, usBufLen);
}


/**
 * @fn      void Gh3x2xSerialSendTimerInit(GU8 uchPeriodMs)
 *
 * @brief  Gh3x2xSerialSendTimerInit
 *
 * @attention   None
 *
 * @param[in]   uchPeriodMs    timer period (ms)
 * @param[out]  None
 *
 * @return  None
 */
void Gh3x2xSerialSendTimerInit(GU8 uchPeriodMs)
{
    // Create timers.
    gh3x2x_ble_send_timer = xTimerCreate("TIMER_GDX", pdMS_TO_TICKS(__GH3X2X_PROTOCOL_SEND_TIMER_PERIOD__), pdTRUE, NULL, Gh3x2xSerialSendTimerHandle);
    if (NULL == gh3x2x_ble_send_timer)
    {
        APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
    }

}


/**
 * @fn     void Gh3x2xSerialSendTimerStop(void)
 *
 * @brief  Serial send timer stop
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void Gh3x2xSerialSendTimerStop(void)
{
    GOODIX_PLANFROM_SERIAL_TIMER_STOP_ENTITY();

    if (gh3x2x_ble_send_timer)
	{
        // Start application timers.
        if (pdPASS != xTimerStop(gh3x2x_ble_send_timer, 0))
        {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
	}
}



/**
 * @fn     void Gh3x2xSerialSendTimerStart(void)
 *
 * @brief  Serial send timer start
 *
 * @attention   None
 *
 * @param[in]   None
 * @param[out]  None
 *
 * @return  None
 */
void Gh3x2xSerialSendTimerStart(void)
{
    GOODIX_PLANFROM_SERIAL_TIMER_START_ENTITY();
    
    if (gh3x2x_ble_send_timer)
	{
        // Start application timers.
        if (pdPASS != xTimerStart(gh3x2x_ble_send_timer, 0))
        {
            APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
        }
	}
}

#endif





void* Gh3x2xMallocUser(GU32 unMemSize)
{
#if (__USER_DYNAMIC_DRV_BUF_EN__)
#ifdef GOODIX_DEMO_PLANFORM
    GOODIX_PLANFROM_MALLOC_USER_ENTITY();
#else
    //return malloc(unMemSize);
    return 0;
#endif
#else
    return 0;
#endif
}

void Gh3x2xFreeUser(void* MemAddr)
{
#if (__USER_DYNAMIC_DRV_BUF_EN__)
    GOODIX_PLANFROM_FREE_USER_ENTITY();
    //free(MemAddr);
#endif
}









#if ( __FUNC_TYPE_BP_ENABLE__ && (__GH3X2X_INTERFACE__ == __GH3X2X_INTERFACE_I2C__))
/**
 * @fn     GS8 gh3x2x_write_pressure_parameters(GS32 *buffer)
 * 
 * @brief  gh3x2x get pressure value
 *
 * @attention   None
 *
 * @param[out]   buffer     buffer[0] = rawdata_a0,
 *                          buffer[1] = rawdata_a1,
 *                          buffer[2] = pressure g value of rawdata_a1,
 *
 * @return  error code
 */
GS8 gh3x2x_write_pressure_parameters(GS32 *buffer)
{
    return GOODIX_PLANFROM_PRESSURE_PARAS_WRITE_ENTITY();
}

/**
 * @fn     GS8 gh3x2x_read_pressure_parameters(GS32 *buffer)
 * 
 * @brief  gh3x2x get pressure value
 *
 * @attention   None
 *
 * @param[out]   buffer     buffer[0] = area,
 *                          buffer[1] = rawdata_a0,
 *                          buffer[2] = rawdata_a1,
 *                          buffer[3] = pressure g value,
 *
 * @return  error code
 */
GS8 gh3x2x_read_pressure_parameters(GS32 *buffer)
{
    return GOODIX_PLANFROM_PRESSURE_PARAS_READ_ENTITY();
}
#endif





/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/
